/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * bocciawii
 * Copyright (C) Grupo de trabajo ULE 2010 <ulewii@googlegroups.com>
 * 
 * bocciawii is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * bocciawii is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _CAMARA_H_
#define _CAMARA_H_

#include <cmath>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include "error-log.h"
#include "obj-loader.h"

#define CAMARA_PRIMERA_PERSONA 10
#define CAMARA_ESTADIO 20
#define CAMARA_AEREA 30
#define N 1
#define S 2
#define E 4
#define O 8
#define NE 5
#define NO 9
#define SE 6
#define SO 10
#define ZOOMMAS 109
#define ZOOMMENOS 110

#define EJEMAYOR 12
#define EJEMENOR 6
#define VANGULAR 0.5
#define DESPLAZAMIENTO 0.015

#define MAXZOOM 0.5
#define MINZOOM 1.5
#define MAXZOOM_AEREA 0.3
#define MINZOOM_AEREA 1.2
#define MAXALTURA 5
#define MAXPRIMERA 2
#define MINPRIMERA -5
#define MINSUELO 2.5
#define MAXLATERAL 8


/**
 * @brief Clase que controla las cámaras
 *
 * En esta clase se define el control de las cámaras de visualización de la escena.
 * Se utilizan 3 cámaras.
 * La cámara de primera persona representa la visión del jugador. La libertad de movimiento es limitada.
 * La cámara de estadio representa una cámara que se mueve sobre raíles fijos alrededor de la pista.
 * La cámara aérea representa una cámara que mira siempre debajo de sí misma. Es una cámara móvil colgada del techo.
 *
 */


/**
 * @brief Vector unitario de otro vector
 *
 * Calcula un vector de módulo 1 con la misma dirección que otro dado
 * @param vector Vector de tres coordenadas
 * @return Un vector de tres coordenadas unitario
 */
float* GetUnitario(float* vector);

class Camara
{
public:
	/** 
	 * @brief Constructor de la clase
	 *
	 * Constructor sencillo, inicializa variables
	 * @param init_x Coordenada x del centro del primer box
	 * @param init_z Coordenada z del centro del primer box
	 * @param x_cen Coordenada x de la cruz central de la pista
	 * @param z_cen Coordenada z de la cruz central de la pista
	 */
	Camara(float init_x, float init_z, float x_cen, float z_cen);

	/** 
	 * @brief Destructor de la clase
	 */
	~Camara();

	/** 
	 * @brief Elige una cámara
	 *
	 * Activa una cámara de entre las tres posibles
	 * @param cam Identificador de la cámara
	 * @param opcion Opción de activación
	 */
	void ActivaCamara(int cam, int opcion);

	/** 
	 * @brief Visualiza la escena
	 *
	 * Utiliza la cámara activa y sus parámetros para establecer la cámara y su
	 * objetivo.
	 */
	void Mirar();

	/** 
	 * @brief Selecciona el box activo
	 *
	 * Establece la cámara de primera persona en el centro del box indicado
	 * @param b Número de box
	 */
	void EligeBox(int b);
	
	/** 
	 * @brief Gestión de eventos de cámara
	 *
	 * Gestiona los eventos de la cámara y modifica los parámetros de la cámara
	 * @param evento El evento de cámara
	 * @param factorx Factor de desplazamiento en el eje x
	 * @param factory Factor de desplazamiento en el eje y
	 * @param delta Diferencia de tiempo
	 */
	void GestionaEvento(int evento, float factorx, float factory, long int delta);

	/** 
	 * @brief Dirección hacia la que se mira
	 * 
	 * Devuelve el vector dirección que indica hacia dónde mira el jugador desde
	 * su box. Ignora la coordenada vertical.
	 * @return Vector unitario de tres coordenadas que contiene la dirección
	 */
	float* GetDireccion();	

	/** 
	 * @brief Obtiene las coordenadas del box
	 * 
	 * Devuelve un vector de tres coordenadas que indican el centro del box activo
	 * @return Coordenadas del box
	 */
	float* GetPosicionBox();
		
	/** 
	 * @brief Devuelve la cámara activa
	 * 
	 * Devuelve un identificador que indica cuál de las tres cámaras está activa
	 * @return Identificador de la cámara
	 */
	inline int GetActiva()
	{ return activa; }

	/** 
	 * @brief Obtiene el box activo
	 * 
	 * Devuelve el número del box activo
	 * @return Un valor de 1 a 6 indicando el box activo
	 */
	inline int GetBox()
	{ return box_activo; }

protected:

private:
	typedef struct  
	{
		float x;
		float y;
		float z;
	} box;

	void CalculaCamara();
	

	int activa; /// Indica la cámara que se está utilizando
	int box_activo; /// Indica el box desde el que se mira (sólo 1ª persona)
		
	float x_centro, z_centro;
	ErrorLog* log; /// Puntero a nuestra clase para Log
	
	float* datos_primera; // Guardo la posición hacia la que mira
	box* posiciones_primera; // Posiciones del centro de los 6 boxes
	float* datos_estadio; // Por este orden, ángulo, zoom, altura
	float* datos_aerea; // Guarda la posición de la cámara y el zoom

	float posx, posy, posz; // Posición de la cámara
	float tox, toy, toz; // Objetivo de la cámara
	float upx, upy, upz; // Vertical de la cámara

	
};

#endif // _CAMARA_H_
